import { newArrMethods } from './array';
import { isObject, isArray, setConstantProperty } from '../utils';

class Observer {
  constructor(data) {
    // 设置常量的属性，如果存在 __ob__属性，就return
    setConstantProperty(data, '__ob__', this);

    // 区分数据是对象还是数组
    if (isArray(data)) {
      data.__proto__ = newArrMethods; // 数组方法重写
      this.observeArr(data);
    } else {
      this.walk(data);
    }
  }

  walk(data) { // 处理对象
    const keys = Object.keys(data);

    keys.map(key => {
      defineReactive(data, key, data[key]);
    })
  }

  observeArr(data) { // 处理数组
    data.map(item => {
      observe(item);
    })
  }

}

function defineReactive(data, key, value) {
  observe(value);

  Object.defineProperty(data, key, {
    get() {
      console.log('响应式数据: 获取', value);
      return value;
    },
    set(newVal) {
      if(value === newVal) return;
      console.log('响应式数: 设置', newVal);
      observe(newVal);
      value = newVal;
    }
  })
}

export function observe(data) {
  // 如果 __ob__ 属性存在 或 不是对象类型
  if (!isObject(data) || data.__ob__) return data;

  new Observer(data);
}